'''
Created on Oct 14, 2011

@author: u
'''


import numpy as np

def bin_to_hop(v):
    """
    convert [0, 1] to [-1, 1]
    """
    return 2 * v - 1

def hop_to_bin(v):
    """
    convert [-1, 1] to [0, 1]
    """
    return (v + 1) / 2

def new_network(size):
    """
    size : size of network
    """
    return np.zeros((size, size))

def step(m, vec):
    """
    m : network matrix
    vec : step vector
    """
    
    m_ = m.copy()
    np.fill_diagonal(m_, 0)
    #print((np.dot(m_,vec) >= 0).astype("int8")*2 -1)
    
    # dot: multiplie chaque ligne de m_ par vec
    return bin_to_hop((np.dot(m_, vec) >= 0).astype("int8"))

def work(m, res):
    """
    m : weight matrix
    res: input pattern to match
    """
    
    results = set()
    #we need to convert numpy arrays to a tuple to store them in a set
    res_flattened = tuple(res)
    while not res_flattened in results:
        results.add(res_flattened)
        res = step(m, res)
        res_flattened = tuple(res)
    
    return res
        
def learn(m, patterns):
    """
    m : network
    patterns : list of vectors to update the network
    """   
    
    for pattern in patterns:
        sample_m = np.ndarray(shape=(len(pattern), len(pattern)))
        row, col = np.indices((len(pattern), len(pattern)))
        #generates the i,j weights by multiplying two 2d arrays
        sample_m = pattern[row] * pattern[col]
        np.fill_diagonal(sample_m, 0)
               
        m += sample_m    

